#############################################################################
##
#W  equivlist.gi             DifSets Package                     Dylan Peifer
##
##  Functions take in a list of difference sets/sums and return a list with
##  equivalent sets/sums removed.
##

#############################################################################
##
#F  EquivalentFreeListOfDifferenceSets( <G>, <difsets> )
##
InstallGlobalFunction( EquivalentFreeListOfDifferenceSets, function (G, difsets)
    local v, prod, auts, newdifsets, D, aut, i, d;

    # make difsets a set of immutable elements so we can use binary search
    # each difset must be a set so that permutations don't matter
    Apply(difsets, x->Immutable(Set(x)));
    difsets := Set(difsets);

    # handle special case of trivial input
    if Length(difsets) <= 1 then return difsets; fi;

    v := Size(G);
    prod := ProductTable(G);
    auts := AutomorphismsTable(G);
    newdifsets := []; # will store inequivalent difsets
 
    while Length(difsets) > 0 do

        # remove a difset and add to the equivalent-free list
        D := Remove(difsets);
        Add(newdifsets, D);

        # remove anything equivalent to D from difsets
        for aut in auts do
        for i in [1..v] do
            d := Set(D, x->prod[i][aut[x]]);
            RemoveSet(difsets, d);
        od;
        od;

    od;

    return newdifsets;
end );

#############################################################################
##
#F  EquivalentFreeListOfDifferenceSetPairs( <G>, <difsetpairs> )
##
# FEATURE EquivalentFreeListOfDifferenceSetPairs(G, difsetpairs)
InstallGlobalFunction( EquivalentFreeListOfDifferenceSetPairs, function (G, difsetpairs)
    local v, prod, auts, newdifsetpairs, DSP, aut, i, d1, d2;

    # make difsetpairs a set of immutable elements so we can use binary search
    for i in [1..Length(difsetpairs)] do
        Sort(difsetpairs[i][1]);  # permutations don't matter
        Sort(difsetpairs[i][2]);
    od;
    Apply(difsetpairs, x->Immutable(x));
    difsetpairs := Set(difsetpairs);

    # handle special case of trivial input
    if Length(difsetpairs) <= 1 then return difsetpairs; fi;

    v := Size(G);
    prod := ProductTable(G);
    auts := AutomorphismsTable(G);
    newdifsetpairs := []; # will store inequivalent difsetpairs
 
    while Length(difsetpairs) > 0 do

        # remove a difsetpair and add to the equivalent-free list
        DSP := Remove(difsetpairs);
        Add(newdifsetpairs, DSP);

        # remove anything equivalent to DSP from difsetpairs
        for aut in auts do
        for i in [1..v] do
            d1 := Set(DSP[1], x->prod[i][aut[x]]);
            difsetpairs := Filtered(difsetpairs, x-> (x[1]<>d1));
        od;
        od;

    od;

    return newdifsetpairs;
end );

#############################################################################
##
#F  EquivalentFreeListOfDivisibleDifferenceSets( <G>, <diviDiffSets>)
##
# FEATURE EquivalentFreeListOfDivisibleDifferenceSets(G, diviDiffSets)
InstallGlobalFunction( EquivalentFreeListOfDivisibleDifferenceSets, function (G, diviDiffSets)
    local n, prod, auts, newdiviDiffSets, D, aut, i, d;

    # make diviDiffSets a set of immutable elements so we can use binary search
    # each diviDiffSets must be a set so that permutations don't matter
    Apply(diviDiffSets, x->Immutable(Set(x)));
    diviDiffSets := Set(diviDiffSets);

    # handle special case of trivial input
    if Length(diviDiffSets) <= 1 then return diviDiffSets; fi;

    n := Size(G);
    prod := ProductTable(G);
    auts := AutomorphismsTable(G);
    newdiviDiffSets := []; # will store inequivalent diviDiffSets

    while Length(diviDiffSets) > 0 do

        # remove a diviDiffSet and add to the equivalent-free list
        D := Remove(diviDiffSets);
        Add(newdiviDiffSets, D);

        # remove anything equivalent to D from diviDiffSets
        for aut in auts do
        for i in [1..n] do
            d := Set(D, x->prod[i][aut[x]]);
            RemoveSet(diviDiffSets, d);
        od;
        od;

    od;

    return newdiviDiffSets;
end );

#############################################################################
##
#F  EquivalentFreeListOfDivisibleDifferenceSetPairs( <G>, <diviDiffSetPairs>)
##
# FEATURE EquivalentFreeListOfDivisibleDifferenceSetPairs(G, diviDiffSetPairs)
InstallGlobalFunction( EquivalentFreeListOfDivisibleDifferenceSetPairs, function (G, diviDiffSetPairs)
    local n, prod, auts, newdiviDiffSetPairs, DDSP, aut, i, d1, d2;

    # make diviDiffSetPairs a set of immutable elements so we can use binary search
    for i in [1..Length(diviDiffSetPairs)] do
        Sort(diviDiffSetPairs[i][1]);
        Sort(diviDiffSetPairs[i][2]);
    od;
    Apply(diviDiffSetPairs, x->Immutable(x));
    diviDiffSetPairs := Set(diviDiffSetPairs);

    # handle special case of trivial input
    if Length(diviDiffSetPairs) <= 1 then return diviDiffSetPairs; fi;

    n := Size(G);
    prod := ProductTable(G);
    auts := AutomorphismsTable(G);
    newdiviDiffSetPairs := []; # will store inequivalent diviDiffSetPairs
 
    while Length(diviDiffSetPairs) > 0 do

        # remove a dividifsetpair and add to the equivalent-free list
        DDSP := Remove(diviDiffSetPairs);
        Add(newdiviDiffSetPairs, DDSP);

        # remove anything equivalent to DDSP from diviDiffSetPairs
        for aut in auts do
        for i in [1..n] do
            d1 := Set(DDSP[1], x->prod[i][aut[x]]);
            diviDiffSetPairs := Filtered(diviDiffSetPairs, x-> (x[1]<>d1));
        od;
        od;

    od;

    return newdiviDiffSetPairs;
end );



#############################################################################
##
#F  TranslateFreeListOfDifferenceSets( <G>, <difsets> )
##
InstallGlobalFunction( TranslateFreeListOfDifferenceSets, function (G, difsets)
    local v, prod, newdifsets, D, i, d;

    # make difsets a set of immutable elements so we can use binary search
    # each difset must be a set so that permutations don't matter
    Apply(difsets, x->Immutable(Set(x)));
    difsets := Set(difsets);

    # handle special case of trivial input
    if Length(difsets) <= 1 then return difsets; fi;

    v := Size(G);
    prod := ProductTable(G);
    newdifsets := []; # will store inequivalent difsets
 
    while Length(difsets) > 0 do

        # remove a difset and add to the equivalent-free list
        D := Remove(difsets);
        Add(newdifsets, D);

        # remove anything translationally equivalent to D from difsets
        for i in [1..v] do
            d := Set(D, x->prod[i][x]);
            RemoveSet(difsets, d);
        od;

    od;

    return newdifsets;
end );

#############################################################################
##
#F  EquivalentFreeListOfDifferenceSums( <G>, <N>, <difsums> )
##
InstallGlobalFunction( EquivalentFreeListOfDifferenceSums, function (G, N, difsums)
    local v, w,prod, auts, newdifsums, S, aut, i, s, j;

    # make difsums a set of immutable elements so we can use binary search
    Apply(difsums, x->Immutable(x));
    difsums := Set(difsums);

    # handle special case of trivial input
    if Length(difsums) <= 1 then return difsums; fi;

    v := Size(G);
    w := Size(N);
    prod := ProductTable(G/N);
    auts := InducedAutomorphismsTable(G, N);
    newdifsums := []; # will store inequivalent difsums

    while Length(difsums) > 0 do

        # remove a difsum and add it to the equivalent-free list
        S := Remove(difsums);
        Add(newdifsums, S);

        # remove anything equivalent to S from difsums
        for aut in auts do
        for i in [1..v/w] do
            s := EmptyPlist(v/w);
            for j in [1..v/w] do
                s[prod[i][aut[j]]] := S[j];
            od;
            RemoveSet(difsums, s);
        od;
        od;

    od;

    return newdifsums;
end );

#############################################################################
##
#F  EquivalentFreeListOfDifferenceSumsOfDifferenceSetPairs( <G>, <N>, <difsums>)
##
# FEATURE EquivalentFreeListOfDifferenceSumsOfDifferenceSetPairs(G, N, difsums)
InstallGlobalFunction( EquivalentFreeListOfDifferenceSumsOfDifferenceSetPairs, function (G, N, difsums)
    local v, w,prod, auts, newdifsums, S, aut, i, s, j;

    # make difsums a set of immutable elements so we can use binary search
    Apply(difsums, x->Immutable(x));
    difsums := Set(difsums);

    # handle special case of trivial input
    if Length(difsums) <= 1 then return difsums; fi;

    v := Size(G);
    w := Size(N);
    prod := ProductTable(G/N);
    auts := InducedAutomorphismsTable(G, N);
    newdifsums := []; # will store inequivalent difsums

    while Length(difsums) > 0 do

        # remove a difsum and add it to the equivalent-free list
        S := Remove(difsums);
        Add(newdifsums, S);

        # remove anything equivalent to S from difsums
        for aut in auts do
        for i in [1..v/w] do
            s := EmptyPlist(v/w);
            for j in [1..v/w] do
                s[prod[i][aut[j]]] := S[1][j];
            od;
            difsums := Filtered(difsums, x-> (x[1]<>s));
        od;
        od;

    od;

    return newdifsums;
end );

#############################################################################
##
#F  EquivalentFreeListOfDifferenceSumsOfDivisibleDifferenceSets( <G>, <N>, <difsums>)
##
# FEATURE EquivalentFreeListOfDifferenceSumsOfDivisibleDifferenceSets(G, N, difsums)
InstallGlobalFunction( EquivalentFreeListOfDifferenceSumsOfDivisibleDifferenceSets, function (G, N, difsums)
    local n, m,prod, auts, newdifsums, S, aut, i, s, j;

    # make difsums a set of immutable elements so we can use binary search
    Apply(difsums, x->Immutable(x));
    difsums := Set(difsums);

    # handle special case of trivial input
    if Length(difsums) <= 1 then return difsums; fi;

    n := Size(G);
    m := Size(N);
    prod := ProductTable(G/N);
    auts := InducedAutomorphismsTable(G, N);
    newdifsums := []; # will store inequivalent difsums

    while Length(difsums) > 0 do

        # remove a difsum and add it to the equivalent-free list
        S := Remove(difsums);
        Add(newdifsums, S);

        # remove anything equivalent to S from difsums
        for aut in auts do
        for i in [1..n/m] do
            s := EmptyPlist(n/m);
            for j in [1..n/m] do
                s[prod[i][aut[j]]] := S[j];
            od;
            RemoveSet(difsums, s);
        od;
        od;

    od;

    return newdifsums;
end );

#############################################################################
##
#F  EquivalentFreeListOfDifferenceSumsOfDivisibleDifferenceSetPairs( <G>, <N>, <difsums>)
##
# FEATURE EquivalentFreeListOfDifferenceSumsOfDivisibleDifferenceSetPairs(G, N, difsums)
InstallGlobalFunction( EquivalentFreeListOfDifferenceSumsOfDivisibleDifferenceSetPairs, function (G, N, difsums)
    local n, m,prod, auts, newdifsums, S, aut, i, s, j;

    # make difsums a set of immutable elements so we can use binary search
    Apply(difsums, x->Immutable(x));
    difsums := Set(difsums);

    # handle special case of trivial input
    if Length(difsums) <= 1 then return difsums; fi;

    n := Size(G);
    m := Size(N);
    prod := ProductTable(G/N);
    auts := InducedAutomorphismsTable(G, N);
    newdifsums := []; # will store inequivalent difsums

    while Length(difsums) > 0 do

        # remove a difsum and add it to the equivalent-free list
        S := Remove(difsums);
        Add(newdifsums, S);

        # remove anything equivalent to S from difsums
        for aut in auts do
        for i in [1..n/m] do
            s := EmptyPlist(n/m);
            for j in [1..n/m] do
                s[prod[i][aut[j]]] := S[1][j];
            od;
            difsums := Filtered(difsums, x-> (x[1]<>s));
        od;
        od;

    od;

    return newdifsums;
end );



#############################################################################
##
#F  TranslateFreeListOfDifferenceSums( <G>, <N>, <difsums> )
##
InstallGlobalFunction( TranslateFreeListOfDifferenceSums, function (G, N, difsums)
    local v, w, prod, newdifsums, S, i, s, j;

    # make difsums a set of immutable elements so we can use binary search
    Apply(difsums, x->Immutable(x));
    difsums := Set(difsums);

    # handle special case of trivial input
    if Length(difsums) <= 1 then return difsums; fi;

    v := Size(G);
    w := Size(N);
    prod := ProductTable(G/N);
    newdifsums := []; # will store inequivalent difsums

    while Length(difsums) > 0 do

        # remove a difsum and add it to the equivalent-free list
        S := Remove(difsums);
        Add(newdifsums, S);

        # remove anything equivalent to S from difsums
        for i in [1..v/w] do
            s := EmptyPlist(v/w);
            for j in [1..v/w] do
                s[prod[i][j]] := S[j];
            od;
            RemoveSet(difsums, s);
        od;

    od;

    return newdifsums;
end );


#############################################################################
##
#E

